/* settings.cpp - this file is part of PixelMerge
 *
 * Copyright (C) 2010 Pascal Giard
 *
 * Author: Pascal Giard <evilynux@gmail.com>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This file is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "settings.h"
#include <unistd.h>

const char * whitespaceCb(mxml_node_t *node, int where);

Settings::Settings() {
  loadDefault();  // Load default settings
  loadFile();     // Overwrite settings with user ones
  // Init array and variable used in settings GUI
  validLanguages[0] = CONF_LANG_ENGLISH;
  validLanguages[1] = CONF_LANG_FRENCH;
  validLanguages[2] = CONF_LANG_CONSOLE;
  validLanguages[3] = CONF_LANG_DEFAULT;
  curValidLang = 0;
  for(u8 i = 0; i < NBR_VALID_LANG; i++) {
    if(user.language[ARRAY_USER] == validLanguages[i]) {
      curValidLang = i;
      break;
    }
  }
//   LoadLanguage(user.language[ARRAY_USER]); // Initialize translation
  reloadLanguage(); // Initialize translation
}

Settings::~Settings() {}

const char * Settings::getNextValidLanguage() {
  curValidLang = (curValidLang + 1) % NBR_VALID_LANG;
  user.language[ARRAY_USER] = validLanguages[curValidLang];

  return getLanguage(user.language[ARRAY_USER]);
}

const char * Settings::getPreviousValidLanguage() {
  if(curValidLang == 0) {
    curValidLang = NBR_VALID_LANG - 1;
  } else {
    curValidLang--;
  }
  user.language[ARRAY_USER] = validLanguages[curValidLang];

  return getLanguage(user.language[ARRAY_USER]);
}

const char * Settings::getLanguage() {
  return getLanguage(user.language[ARRAY_USER]);
}

const char * Settings::getLanguage(u8 lang) {
  switch(lang)
    {
//     case CONF_LANG_JAPANESE: 
//       return _("Japenese");
    case CONF_LANG_ENGLISH: 
      return _("English");
//     case CONF_LANG_GERMAN: 
//       return _("German");
    case CONF_LANG_FRENCH:
      return _("French");
//     case CONF_LANG_SPANISH:
//       return _("Spanish");
//     case CONF_LANG_ITALIAN:
//       return _("Italian");
//     case CONF_LANG_DUTCH: 
//       return _("Dutch");
//     case CONF_LANG_SIMP_CHINESE:
//       return _("S. Chinese");
//     case CONF_LANG_TRAD_CHINESE:
//       return _("T. Chinese");
//     case CONF_LANG_KOREAN:
//       return _("Korean");
    case CONF_LANG_DEFAULT:
      return _("Default");
    case CONF_LANG_CONSOLE:
      return _("Console");
    default:
      return _("Default");
    }
}

void Settings::reloadLanguage() {
  if(validLanguages[curValidLang] == CONF_LANG_CONSOLE)
    LoadLanguage(user.language[ARRAY_CONSOLE]);
  else if(validLanguages[curValidLang] == CONF_LANG_DEFAULT)
    LoadLanguage(user.language[ARRAY_DEFAULT]);
  else
    LoadLanguage(user.language[ARRAY_USER]);
}

// Load default settings
void Settings::loadDefault() {
  user.record[EASY] = 0;
  user.record[NORMAL] = 0;
  user.record[HARD] = 0;
  user.autoSave = 1;
  user.language[ARRAY_CONSOLE] = CONF_GetLanguage();
  user.language[ARRAY_DEFAULT] = CONF_LANG_ENGLISH;
  user.language[ARRAY_USER] = CONF_GetLanguage();
  video.offsetX = 0;
  video.offsetY = 0;
  video.scaleX = 100;
  video.scaleY = 100;
  board[EASY].nbrRows = 14;
  board[EASY].size = 400;
  board[EASY].nbrSteps = 25;
  board[NORMAL].nbrRows = 21;
  board[NORMAL].size = 420;
  board[NORMAL].nbrSteps = 35;
  board[HARD].nbrRows = 28;
  board[HARD].size = 448;
  board[HARD].nbrSteps = 50;
}

// Load preferences from file
bool Settings::loadFile() {
  mxml_node_t *tree;
  mxml_node_t *data;
  const char * tmp;

  FILE *fp = fopen("pixelmerge.cfg", "rb");
  if (fp == NULL) {
    return false;
  }

  fseek (fp , 0, SEEK_END);
  long settings_size = ftell (fp);
  rewind (fp);

  if (settings_size == 0) {
    fclose(fp);
    unlink("pixelmerge.cfg");
    return false;
  }

  tree = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK);
  fclose(fp);

  data = mxmlFindElement(tree, tree, "file", NULL, NULL, MXML_DESCEND);
  if(data) {
    tmp = mxmlElementGetAttr(data, "app");
    if (strcmp(tmp, "PixelMerge")) { // App not PixelMerge ==> Not our file!
      return false;
    }
  }
  data = mxmlFindElement(tree, tree, "screen", NULL, NULL, MXML_DESCEND);
  if(data) {
    tmp = mxmlElementGetAttr(data, "offsetX");
    if(tmp) video.offsetX = atoi(tmp);
    tmp = mxmlElementGetAttr(data, "offsetY");
    if(tmp) video.offsetY = atoi(tmp);
    tmp = mxmlElementGetAttr(data, "scaleX");
    if(tmp) video.scaleX = atoi(tmp);
    tmp = mxmlElementGetAttr(data, "scaleY");
    if(tmp) video.scaleY = atoi(tmp);
  }
  data = mxmlFindElement(tree, tree, "records", NULL, NULL, MXML_DESCEND);
  if(data) {
    tmp = mxmlElementGetAttr(data, "easy");
    if(tmp) user.record[EASY] = atoi(tmp);
    tmp = mxmlElementGetAttr(data, "normal");
    if(tmp) user.record[NORMAL] = atoi(tmp);
    tmp = mxmlElementGetAttr(data, "hard");
    if(tmp) user.record[HARD] = atoi(tmp);
  }
  data = mxmlFindElement(tree, tree, "saving", NULL, NULL, MXML_DESCEND);
  if(data) {
    tmp = mxmlElementGetAttr(data, "auto");
    if(tmp) user.autoSave = atoi(tmp);
  }
  data = mxmlFindElement(tree, tree, "language", NULL, NULL, MXML_DESCEND);
  if(data) {
    tmp = mxmlElementGetAttr(data, "user");
    if(tmp) user.language[ARRAY_USER] = atoi(tmp);
  }
  mxmlDelete(tree);

  return true;
}

// Save preferences to file
bool Settings::save() {
  mxml_node_t *xml;
  mxml_node_t *file;
  mxml_node_t *data;
  char set[5];

  xml = mxmlNewXML("1.0");

  file = mxmlNewElement(xml, "file");
  mxmlElementSetAttr(file, "app", "PixelMerge");
  mxmlElementSetAttr(file, "version", "1.0.0");

  data = mxmlNewElement(file, "screen");
  snprintf(set, sizeof(set), "%i", video.offsetX);
  mxmlElementSetAttr(data, "offsetX", set);
  snprintf(set, sizeof(set), "%i", video.offsetY);
  mxmlElementSetAttr(data, "offsetY", set);
  snprintf(set, sizeof(set), "%i", video.scaleX);
  mxmlElementSetAttr(data, "scaleX", set);
  snprintf(set, sizeof(set), "%i", video.scaleY);
  mxmlElementSetAttr(data, "scaleY", set);

  data = mxmlNewElement(file, "records");
  snprintf(set, sizeof(set), "%i", user.record[EASY]);
  mxmlElementSetAttr(data, "easy", set);
  snprintf(set, sizeof(set), "%i", user.record[NORMAL]);
  mxmlElementSetAttr(data, "normal", set);
  snprintf(set, sizeof(set), "%i", user.record[HARD]);
  mxmlElementSetAttr(data, "hard", set);

  data = mxmlNewElement(file, "saving");
  snprintf(set, sizeof(set), "%i", user.autoSave);
  mxmlElementSetAttr(data, "auto", set);

  data = mxmlNewElement(file, "language");
  snprintf(set, sizeof(set), "%i", user.language[ARRAY_DEFAULT]);
  mxmlElementSetAttr(data, "default", set);
  snprintf(set, sizeof(set), "%i", user.language[ARRAY_CONSOLE]);
  mxmlElementSetAttr(data, "console", set);
  snprintf(set, sizeof(set), "%i", user.language[ARRAY_USER]);
  mxmlElementSetAttr(data, "user", set);

  FILE *f;
  f = fopen("pixelmerge.cfg", "wb"); // Save to current folder

  // Settings could not be written
  if (f == NULL) {
    mxmlDelete(xml);
    return false;
  }

  mxmlSaveFile(xml, f, whitespaceCb);
  fclose(f);
  mxmlDelete(xml);
  
  return true; // Success!
}

void Settings::resetRecords() {
  user.record[EASY] = 0;
  user.record[NORMAL] = 0;
  user.record[HARD] = 0;
  save();
}

// Whitespace callback for proper xml file indentation
const char * whitespaceCb(mxml_node_t *node, int where) {
  const char *name;

  name = node->value.element.name;

  if (!strcmp(name, "file")) {
    if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_AFTER_OPEN ||
        where == MXML_WS_AFTER_CLOSE) {
      return ("\n");
    }
  } else if (!strcmp(name, "screen") || !strcmp(name, "records") ||
             !strcmp(name, "saving") || !strcmp(name, "language")) {
    if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_BEFORE_CLOSE) {
      return ("\t");
    } else if (where == MXML_WS_AFTER_OPEN || where == MXML_WS_AFTER_CLOSE) {
      return ("\n");
    }
  }
  return (NULL); // Don't add a whitespace.
}
